home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / dig-2.0 / dig-2 / dig.2.0 / res_mkquery.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-04  |  5.5 KB  |  219 lines

  1.  
  2. /*
  3.  * Copyright (c) 1985 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that this notice is preserved and that due credit is given
  8.  * to the University of California at Berkeley. The name of the University
  9.  * may not be used to endorse or promote products derived from this
  10.  * software without specific prior written permission. This software
  11.  * is provided ``as is'' without express or implied warranty.
  12.  */
  13.  
  14. /*
  15. ** Distributed with 'dig' version 2.0 from University of Southern
  16. ** California Information Sciences Institute (USC-ISI). 9/1/90
  17. */
  18.  
  19. #if defined(LIBC_SCCS) && !defined(lint)
  20. static char sccsid[] = "@(#)res_mkquery.c    6.7 (Berkeley) 3/7/88";
  21. #endif /* LIBC_SCCS and not lint */
  22.  
  23. #include "hfiles.h"
  24.  
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <netinet/in.h>
  28. #include NAMESERH
  29. #ifndef T_TXT
  30. #define T_TXT 16
  31. #endif T_TXT
  32. #include RESOLVH
  33.  
  34. #ifndef RES_DEBUG2
  35. #define RES_DEBUG2      0x80000000
  36. #endif
  37.  
  38. /*
  39.  * Form all types of queries.
  40.  * Returns the size of the result or -1.
  41.  */
  42. res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
  43.     int op;            /* opcode of query */
  44.     char *dname;        /* domain name */
  45.     int class, type;    /* class and type of query */
  46.     char *data;        /* resource record data */
  47.     int datalen;        /* length of data */
  48.     struct rrec *newrr;    /* new rr for modify or append */
  49.     char *buf;        /* buffer to put query */
  50.     int buflen;        /* size of buffer */
  51. {
  52.     register HEADER *hp;
  53.     register char *cp;
  54.     register int n;
  55.     char dnbuf[MAXDNAME];
  56.     char *dnptrs[10], **dpp, **lastdnptr;
  57.     extern char *index();
  58.  
  59. #ifdef DEBUG
  60.     if (_res.options & RES_DEBUG2)
  61.       printf(";; res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
  62. #endif DEBUG
  63.     /*
  64.      * Initialize header fields.
  65.      */
  66.     hp = (HEADER *) buf;
  67.     hp->id = htons(++_res.id);
  68.     hp->opcode = op;
  69.     hp->qr = hp->aa = hp->tc = hp->ra = 0;
  70.     hp->aa = (_res.options & RES_AAONLY) != 0;
  71.     hp->tc = (_res.options & RES_IGNTC) != 0;
  72.     hp->pr = (_res.options & RES_PRIMARY) != 0;
  73.     hp->rd = (_res.options & RES_RECURSE) != 0;
  74.     hp->rcode = NOERROR;
  75.     hp->qdcount = 0;
  76.     hp->ancount = 0;
  77.     hp->nscount = 0;
  78.     hp->arcount = 0;
  79.     cp = buf + sizeof(HEADER);
  80.     buflen -= sizeof(HEADER);
  81.     dpp = dnptrs;
  82.     *dpp++ = buf;
  83.     *dpp++ = NULL;
  84.     lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
  85.     /*
  86.      * If the domain name contains no dots (single label), then
  87.      * append the default domain name to the one given.
  88.      */
  89.     if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' &&
  90.         index(dname, '.') == NULL) {
  91.         if (!(_res.options & RES_INIT))
  92.             if (res_init() == -1)
  93.                 return(-1);
  94.         if (_res.defdname[0] != '\0') {
  95.             (void)sprintf(dnbuf, "%s.%s", dname, _res.defdname);
  96.             dname = dnbuf;
  97.         }
  98.     }
  99.     /*
  100.      * perform opcode specific processing
  101.      */
  102.     switch (op) {
  103.     case QUERY:
  104.         buflen -= QFIXEDSZ;
  105.         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
  106.             return (-1);
  107.         cp += n;
  108.         buflen -= n;
  109.         putshort(type, cp);
  110.         cp += sizeof(u_short);
  111.         putshort(class, cp);
  112.         cp += sizeof(u_short);
  113.         hp->qdcount = htons(1);
  114.         if (op == QUERY || data == NULL)
  115.             break;
  116.         /*
  117.          * Make an additional record for completion domain.
  118.          */
  119.         buflen -= RRFIXEDSZ;
  120.         if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
  121.             return (-1);
  122.         cp += n;
  123.         buflen -= n;
  124.         putshort(T_NULL, cp);
  125.         cp += sizeof(u_short);
  126.         putshort(class, cp);
  127.         cp += sizeof(u_short);
  128.         putlong(0, cp);
  129.         cp += sizeof(u_long);
  130.         putshort(0, cp);
  131.         cp += sizeof(u_short);
  132.         hp->arcount = htons(1);
  133.         break;
  134.  
  135.     case IQUERY:
  136.         /*
  137.          * Initialize answer section
  138.          */
  139.         if (buflen < 1 + RRFIXEDSZ + datalen)
  140.             return (-1);
  141.         *cp++ = '\0';    /* no domain name */
  142.         putshort(type, cp);
  143.         cp += sizeof(u_short);
  144.         putshort(class, cp);
  145.         cp += sizeof(u_short);
  146.         putlong(0, cp);
  147.         cp += sizeof(u_long);
  148.         putshort(datalen, cp);
  149.         cp += sizeof(u_short);
  150.         if (datalen) {
  151.             bcopy(data, cp, datalen);
  152.             cp += datalen;
  153.         }
  154.         hp->ancount = htons(1);
  155.         break;
  156.  
  157. #ifdef ALLOW_UPDATES
  158.     /*
  159.      * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
  160.      * (Record to be modified is followed by its replacement in msg.)
  161.      */
  162.     case UPDATEM:
  163.     case UPDATEMA:
  164.  
  165.     case UPDATED:
  166.         /*
  167.          * The res code for UPDATED and UPDATEDA is the same; user
  168.          * calls them differently: specifies data for UPDATED; server
  169.          * ignores data if specified for UPDATEDA.
  170.          */
  171.     case UPDATEDA:
  172.         buflen -= RRFIXEDSZ + datalen;
  173.         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
  174.             return (-1);
  175.         cp += n;
  176.         putshort(type, cp);
  177.                 cp += sizeof(u_short);
  178.                 putshort(class, cp);
  179.                 cp += sizeof(u_short);
  180.         putlong(0, cp);
  181.         cp += sizeof(u_long);
  182.         putshort(datalen, cp);
  183.                 cp += sizeof(u_short);
  184.         if (datalen) {
  185.             bcopy(data, cp, datalen);
  186.             cp += datalen;
  187.         }
  188.         if ( (op == UPDATED) || (op == UPDATEDA) ) {
  189.             hp->ancount = htons(0);
  190.             break;
  191.         }
  192.         /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
  193.  
  194.     case UPDATEA:    /* Add new resource record */
  195.         buflen -= RRFIXEDSZ + datalen;
  196.         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
  197.             return (-1);
  198.         cp += n;
  199.         putshort(newrr->r_type, cp);
  200.                 cp += sizeof(u_short);
  201.                 putshort(newrr->r_class, cp);
  202.                 cp += sizeof(u_short);
  203.         putlong(0, cp);
  204.         cp += sizeof(u_long);
  205.         putshort(newrr->r_size, cp);
  206.                 cp += sizeof(u_short);
  207.         if (newrr->r_size) {
  208.             bcopy(newrr->r_data, cp, newrr->r_size);
  209.             cp += newrr->r_size;
  210.         }
  211.         hp->ancount = htons(0);
  212.         break;
  213.  
  214. #endif ALLOW_UPDATES
  215.     }
  216.     return (cp - buf);
  217. }
  218.  
  219.